package com.mashibing.juc.c_018.AtomicXXX;

import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;

/**
 * 三种不同的方式实现递增
 * @author: Yuanzt
 * @Date: 2021/3/26
 */
public class T02_AtomicVsSynchroziedVsLock {

    static AtomicLong count1 = new AtomicLong(0L);
    static long count2 = 0L;
    static LongAdder count3 = new LongAdder();

    public static void main(String[] args) throws InterruptedException {
        Thread[] threads = new Thread[1000];
        //-----------------------第一种方式Atomic实现--------------------
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(()->{
                for (int k=0;k<100000;k++) count1.incrementAndGet();
            });
        }
        long start = System.currentTimeMillis();

        for (Thread t : threads) t.start();
        for (Thread t : threads) t.join();

        long end = System.currentTimeMillis();
        System.out.println("Atomic: "+count1.get()+" time "+(end-start));
        //-----------------------------第二种方式，基本数据类型加加--------------
        Object lock = new Object();
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(()->{
                for (int k=0;k<100000;k++){
                    synchronized (lock){
                        count2++;
                    }
                }
            });
        }
        start = System.currentTimeMillis();
        for (Thread t : threads) t.start();
        for (Thread t : threads) t.join();
        end = System.currentTimeMillis();
        System.out.println("Sync: "+ count2 + " time "+(end-start));
        //-------------------------第三种LongAdder,在线程特别多的情况下效率最高，因为其使用分段锁（分段锁也是使用CAS实现的）
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(()->{
                for (int k = 0; k < 100000; k++) {
                    count3.increment();
                }
            });
        }
        start = System.currentTimeMillis();
        for (Thread t : threads) t.start();
        for (Thread t : threads) t.join();
        end = System.currentTimeMillis();
        System.out.println("LongAdder: "+count3.longValue()+" time :"+(end-start));
    }
}
